from random import choice
import uuid
from django.contrib.gis.db import models as gis_models
from django.contrib.gis.db.models.fields import Point, Polygon
from ckeditor_uploader.fields import RichTextUploadingField
from django import forms
from filer.fields.image import FilerImageField, FilerFileField
from django.contrib.auth.models import User
from colorfield.fields import ColorField
# from audiofield.fields import AudioField
from django.conf import settings
from django.utils.html import format_html
from django.db import models
from django.utils.safestring import mark_safe

from common.base_model import GisBaseModel, BaseForeignKey, BaseManyToManyField, CronTextField


FOOTER_POSITION = (
    (0, '左侧'),
    (1, '上侧'),
    (2, '右侧'),
    (3, '下侧'),
)

# 图例
class IconLegend(GisBaseModel):
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='景区类型名称')
    icon = FilerImageField(null=True, blank=True, related_name='area_icon', verbose_name='图标', on_delete=gis_models.SET_NULL)
    icon_width = gis_models.IntegerField(null=True, blank=True, verbose_name='图标宽度')
    icon_height = gis_models.IntegerField(null=True, blank=True, verbose_name='图标高度')

    def __str__(self):
        return self.name
    
    class Meta:
        verbose_name = '图例'
        verbose_name_plural = '图例'    


# 景区类型
class ScenicAreaType(GisBaseModel):
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='景区类型名称')
    show = gis_models.BooleanField(default=False, verbose_name='默认显示')
    orderid = gis_models.IntegerField(default=1, null=False, blank=False, verbose_name='排序')

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('orderid',)
        verbose_name = '景区类型'
        verbose_name_plural = '景区类型'


# 景区
class ScenicArea(GisBaseModel): 
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='景区名称')
    is_street = gis_models.BooleanField(default=False, verbose_name='街道') 
    root = gis_models.BooleanField(default=False, verbose_name='根景区')
    show_contour = gis_models.BooleanField(default=False, blank=True, verbose_name='显示轮廓')
    show_contour_in_parent = gis_models.BooleanField(default=False, blank=True, verbose_name='在父景区内显示轮廓')
    contour_color = ColorField(null=False, blank=False, default='#FF0000', verbose_name="轮廓颜色")
    cma_color = ColorField(null=False, blank=False, default='#C1FFE4', verbose_name="子景区标识颜色")
    popup_width = gis_models.IntegerField(null=True, blank=True, verbose_name='浮出框宽度')
    popup_content = RichTextUploadingField(null=True, blank=True, verbose_name='浮出框内容')
    show_footer = gis_models.BooleanField(default=True, verbose_name='显示景区名称')
    footer_position = gis_models.IntegerField(default=3, choices=FOOTER_POSITION, verbose_name='显示名称位置')
    footer_width = gis_models.IntegerField(null=True, blank=True, default=50, verbose_name='显示名称宽度')
    detail = RichTextUploadingField(verbose_name='详细信息')
    location = gis_models.PointField(null=False, blank=False, verbose_name='坐标', default=settings.SCENIC_CENTER)
    mpoly = gis_models.PolygonField(blank=False, null=False, verbose_name='区域', default=settings.SCENIC_AREA)
    bound_ratio = gis_models.FloatField(blank=False, null=False, default=1, verbose_name='地图显示边界缩放比例', help_text='用于在使用默认地图时, 控制显示的地图边界.值为1时,表示按照景区区域显示地图边界')
    zoom = gis_models.IntegerField(default=18, choices=[(i, i) for i in range(0, 25)], verbose_name='地图默认缩放等级')
    min_zoom = gis_models.IntegerField(default=17, choices=[(i, i) for i in range(0, 25)], verbose_name='地图最小缩放等级')
    max_zoom = gis_models.IntegerField(default=20, choices=[(i, i) for i in range(0, 25)], verbose_name='地图最大缩放等级')
    legend = BaseForeignKey(IconLegend, related_name='scenic_legend', on_delete=gis_models.SET_NULL, null=True, blank=True, verbose_name='图例')
    scenic_area_type = BaseForeignKey(ScenicAreaType, on_delete=gis_models.SET_NULL, null=True, blank=True, verbose_name='景区类型')
    children_scenic_area_type = BaseManyToManyField(ScenicAreaType, blank=True, related_name='chilren_sa_type', verbose_name='需要在菜单栏单独显示的景区类型')
    audio_file = FilerFileField(null=True, blank=True, related_name='scenic_audio', on_delete=gis_models.SET_NULL, help_text=("支持类型 .mp3, .wav, .ogg"), verbose_name='讲解音频')
    audio_detail = RichTextUploadingField(null=True, blank=True, verbose_name='语音台本')
    bg_audio_file = FilerFileField(null=True, blank=True, related_name='scenic_bg_audio', on_delete=gis_models.SET_NULL, help_text=("支持类型 .mp3, .wav, .ogg"), verbose_name='背景音乐')
    modify_db = gis_models.FloatField(null=False, blank=False, default=0, help_text='正值增加,负值减小', verbose_name='调整分贝')
    show_detail = gis_models.BooleanField(default=True, null=False, blank=False, verbose_name='显示详情')
    show_map = gis_models.BooleanField(default=True, null=False, blank=False, verbose_name='显示详情页地图入口')
    show_nav = gis_models.BooleanField(default=True, null=False, blank=False, verbose_name='显示详情页地图导航')
    show_audio = gis_models.BooleanField(default=True, null=False, blank=False, verbose_name='显示详情页音频讲解')
    scenic_area = BaseForeignKey('self', on_delete=gis_models.SET_NULL, null=True, blank=True, verbose_name='所属景区')

    def mname(self):
        if self.scenic_area:
            return format_html('<span style="color: red;">[' + self.scenic_area.name + ']</span>' + self.name)
        else:
            return self.name

    def text2speech(self):
        return format_html('<a href="/api/samap/tts/%d/">合成语音</a>' % self.id)
    text2speech.allow_tags = True
    text2speech.short_description = ('合成语音')

    def has_audio_file(self):
        return  format_html('<img src="/static/admin/img/icon-yes.svg" alt="False">') if self.audio_file else format_html('<img src="/static/admin/img/icon-no.svg" alt="False">')
    has_audio_file.allow_tags = True
    has_audio_file.short_description = ('已有语音')

    # 定义一些操作示例
    def operate(self):
        from .utils import encrypt_scenic_id
        ikey = encrypt_scenic_id(self.id)
        # info_msg = f'{ikey}'
        # # simpleui 用的elementui ,可以使用el的类修改默认样式
        # btn = f"""<button onclick="self.parent.app.$msgbox('{info_msg}')"
        #                     class="el-button el-button--warning el-button--small">识别码</button>"""
        # return mark_safe(f"<div>{btn} </div>")
        # 在新标签中打开修改界面，url可以随意指定。自己可以多做尝试
        data = '{"name": "%s", "icon": "fas fa-user-tie", "url": "/madmin/samap/qrcode/?key=%s"}' % (self.name, ikey)
        btn = f"""<button onclick='self.parent.app.openTab({data})'
                             class='el-button el-button--danger el-button--small'>更多设置</button>"""
        return mark_safe(f"<div>{btn}</div>")
    operate.short_description = ('操作')

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name
    
    class Meta:
        verbose_name = '景区'
        verbose_name_plural = '景区' 


# 景区地图
class ScenicAreaMap(GisBaseModel):
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='名称')
    map_identifier = gis_models.UUIDField(default=uuid.uuid4, null=False, blank=False, verbose_name='地图标识符', help_text='地图唯一标识符')
    left_up =  gis_models.PointField(null=False, blank=False, verbose_name='图片左上角对应经纬度坐标', default=settings.SCENIC_CENTER2)
    right_down =  gis_models.PointField(null=False, blank=False, verbose_name='图片右下角对应经纬度坐标', default=settings.SCENIC_CENTER2)
    zoom = gis_models.IntegerField(default=18, choices=[(i, i) for i in range(0, 25)], verbose_name='地图默认缩放等级')
    min_zoom = gis_models.IntegerField(default=0, choices=[(i, i) for i in range(0, 25)], verbose_name='地图最小缩放等级')
    max_zoom = gis_models.IntegerField(default=20, choices=[(i, i) for i in range(0, 25)], verbose_name='地图最大缩放等级')
    map_image = FilerFileField(null=True, blank=True, related_name='map_image', verbose_name='地图', on_delete=gis_models.SET_NULL)
    scenic_area = BaseForeignKey(ScenicArea, on_delete=gis_models.SET_NULL, null=True, blank=False, verbose_name='所属景区')

    def mname(self):
        if self.scenic_area:
            return format_html('<span style="color: red;">[' + self.scenic_area.name + ']</span>' + self.name)
        else:
            return self.name

    def gdal2tiles(self):
        return format_html('<a href="/api/samap/gdal2tile/%d/">生成地图</a>' % self.id)
    gdal2tiles.allow_tags = True
    gdal2tiles.short_description = ('生成地图')  

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name
    
    class Meta:
        verbose_name = '景区地图'
        verbose_name_plural = '景区地图'


# 运行轨迹
class Track(GisBaseModel):
    user = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='用户标识')
    points = gis_models.LineStringField(null=True, blank=True, verbose_name='轨迹')
    scenic_area = BaseForeignKey(ScenicArea, on_delete=gis_models.CASCADE, null=False, blank=False, verbose_name='所属景区')

    def mname(self):
        if self.scenic_area:
            return format_html('<span style="color: red;">[' + self.scenic_area.name + ']</span>' + self.name)
        else:
            return self.name

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name
    class Meta:
        verbose_name = '运行轨迹'
        verbose_name_plural = '运行轨迹'    


# 路线类型
class RoadType(GisBaseModel):
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='名称')
    detail = RichTextUploadingField(verbose_name='详细信息')
    show = gis_models.BooleanField(default=False, verbose_name='是否默认显示')
    orderid = gis_models.IntegerField(default=1, null=False, blank=False, verbose_name='排序')
    scenic_area = BaseForeignKey(ScenicArea, on_delete=gis_models.SET_NULL, null=True, blank=False, verbose_name='所属景区')

    def mname(self):
        if self.scenic_area:
            return format_html('<span style="color: red;">[' + self.scenic_area.name + ']</span>' + self.name)
        else:
            return self.name

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name

    class Meta:
        ordering = ('orderid',)
        verbose_name = '路线类型'
        verbose_name_plural = '路线类型'


# 路线
class Road(GisBaseModel):
    orderid = gis_models.IntegerField(default=1, null=False, blank=False, verbose_name='排序')
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='名称')
    detail = RichTextUploadingField(verbose_name='详细信息')
    show_route = gis_models.BooleanField(default=False, verbose_name='显示路线')
    route = gis_models.LineStringField(null=False, blank=False, default=settings.SCENIC_LINE, verbose_name='路线')
    contour_color = ColorField(null=False, blank=False, default='#FF0000', verbose_name="显示颜色")
    road_type = BaseForeignKey(RoadType, related_name='roads', on_delete=gis_models.SET_NULL,  null=True, blank=False, verbose_name='类型')
    related_scenics = BaseManyToManyField(ScenicArea, through='RoadScenics',  related_name='related_scenics', blank=True, verbose_name='景区')
    scenic_area = BaseForeignKey(ScenicArea, on_delete=gis_models.SET_NULL, null=True, blank=False, verbose_name='所属景区')

    def mname(self):
        if self.scenic_area:
            return format_html('<span style="color: red;">[' + self.scenic_area.name + ']</span>' + self.name)
        else:
            return self.name

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name
    
    class Meta:
        ordering = ('orderid',)
        verbose_name = '路线'
        verbose_name_plural = '路线'

class RoadScenics(GisBaseModel):    
    road = BaseForeignKey(Road, on_delete=gis_models.CASCADE)
    scenic = BaseForeignKey(ScenicArea, on_delete=gis_models.CASCADE)
    orderid = gis_models.IntegerField(null=False, blank=False, verbose_name='排序')
    
    class Meta:
        ordering = ('orderid',)


class BackgroundMusic(GisBaseModel):
    default = gis_models.BooleanField(default=False, verbose_name='默认')
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='名称')
    bg_audio_file = FilerFileField(null=False, blank=False, related_name='bg_audio', on_delete=gis_models.CASCADE, help_text=("支持类型 .mp3, .wav, .ogg"), verbose_name='背景音乐')
    modify_db = gis_models.FloatField(null=False, blank=False, default=0, help_text='正值增加,负值减小', verbose_name='调整分贝')

    def __str__(self):
        return self.name
    
    class Meta:
        verbose_name = '背景音乐'
        verbose_name_plural = '背景音乐'

class Multimap(GisBaseModel):
    name = gis_models.CharField(max_length=256, null=False, blank=False, verbose_name='名称')
    icon = FilerImageField(null=True, blank=True, related_name='multimap_icon', verbose_name='图标', on_delete=gis_models.SET_NULL)
    icon_width = gis_models.IntegerField(null=True, blank=True, verbose_name='图标宽度')
    icon_height = gis_models.IntegerField(null=True, blank=True, verbose_name='图标高度')
    scenic_area = BaseForeignKey(ScenicArea, related_name="multimap_scenic", on_delete=gis_models.CASCADE, null=True, blank=False, verbose_name='景区')
    orderid = gis_models.IntegerField(null=False, blank=False, verbose_name='排序')

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name + '-' + self.name
        else:
            return self.name
    class Meta:
        ordering = ('orderid',)
        verbose_name = '多地图'
        verbose_name_plural = '多地图'

class CronTask(GisBaseModel):
    task_type_list = (
        (0, '演出任务'),
    )
    grade_list = (
        (1, '一星'),
        (2, '二星'),
        (3, '三星'),
        (4, '四星'),
        (5, '五星'),
    )
    parent_scenic = BaseForeignKey(ScenicArea, related_name="cron_task_parent_scenic", on_delete=gis_models.CASCADE, null=False, blank=False, verbose_name='父景区')
    scenic_area = BaseForeignKey(ScenicArea, related_name="cron_task_scenic", on_delete=gis_models.CASCADE, null=False, blank=False, verbose_name='景区')
    using = gis_models.BooleanField(default=True, verbose_name='正在使用')
    task_type = gis_models.IntegerField(default=0, choices=task_type_list, verbose_name='任务类型')
    grade = gis_models.IntegerField(default=5, choices=grade_list, verbose_name='推荐等级')
    detail = RichTextUploadingField(verbose_name='详细信息')
    cron_task = CronTextField(null=True, blank=True, verbose_name='定时任务')

    # 定义一些操作示例
    def operate(self):
        # 在新标签中打开修改界面，url可以随意指定。自己可以多做尝试
        data = '{"name": "%s", "icon": "fas fa-user-tie", "url": "/madmin/samap/edit_crontask/?cronid=%s"}' % ('修改任务', self.id,)
        btn = f"""<button onclick='self.parent.app.openTab({data})'
                             class='el-button el-button--danger el-button--small'>修改任务</button>"""
        return mark_safe(f"<div>{btn}</div>")
    operate.short_description = ('操作')

    def __str__(self):
        if self.scenic_area:
            return self.scenic_area.name
    class Meta:
        unique_together = ('scenic_area', 'task_type')
        ordering = ('scenic_area', 'task_type')
        verbose_name = '定时任务'
        verbose_name_plural = '定时任务'